package com.sinodata.bsm.cicp.collector.sqlserver;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.AbstractJDBCCollector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.common.vo.ResPropertyValue;

public class Database extends AbstractJDBCCollector {
    private static final Logger logger = Logger.getLogger(Database.class);

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        try {
            String[] propMetas = getPropMeta();
            String serverName = this.getParamMap().get("ServerName");
            String dataName = this.getParamMap().get("DBName");
            String sql = "sp_helpdb";
            String[] rs = this.getStrings(dataName, serverName, sql, ip);

            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
            for (int i = 0; i < propMetas.length; i++) {
                propValues[i] = ResPropertyValue.createPropValue(rs[i], propMetas[i]);
            }

            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (Exception e) {
            logger.error("failed to collect sqlserver database", e);
            throw new CollectorException(e);
        }
        return values;
    }

    private String[] getStrings(String name, String serverName, String sql, String ip) throws CollectorException {
        String[] propValArr = new String[6];

        ResultSet rst = null;
        try {
            float dataSize = 0.0F;
            float dataUnused = 0.0F;
            float logSize = 0.0F;
            float logUsed = 0.0F;

            sql = name + ".dbo.sp_spaceused";
            rst = this.getCachedResultSet("sqlserver", ip, serverName, sql);
            if (rst != null) {
                while (rst.next()) {
                    String sdataSize = rst.getString(2);
                    dataSize = Float.parseFloat(sdataSize.substring(0, sdataSize.length() - 3));
                    String sdataUnused = rst.getString(3);
                    dataUnused = Float.parseFloat(sdataUnused.substring(0, sdataUnused.length() - 3));
                }
            }
            rst.close();
            rst = null;

            //Log size, log used size
            sql = "select* from  master.dbo.sysperfinfo where counter_name like '%Log File%' and instance_name = '" + name + "' order by counter_name";
            rst = this.getCachedResultSet("sqlserver", ip, serverName, sql);
            //DecimalFormat fmt = new DecimalFormat("#.00");
            int i = 0;
            while (rst.next()) {
                if (i == 0) {
                    String slogSize = rst.getString(4);
                    logSize = Float.parseFloat(slogSize) / 1024.0F;
                } else if (i == 1) {
                    String slogUsed = rst.getString(4);
                    logUsed = Float.parseFloat(slogUsed) / 1024.0F;
                } else {
                    break;
                }
                i++;
            }
            rst.close();
            rst = null;

            logSize = formatDecimal(logSize);
            float logUnused = formatDecimal(logSize - logUsed);
            float dataUsedPercent = formatDecimal((dataSize - dataUnused) / dataSize * 100);
            float logUsedPercent = formatDecimal(logUsed / logSize * 100);
            propValArr[0] = dataSize + "";
            propValArr[1] = dataUnused + "";
            propValArr[2] = logSize + "";
            propValArr[3] = logUnused + "";
            propValArr[4] = dataUsedPercent + "";
            propValArr[5] = logUsedPercent + "";

        } catch (Exception ex) {
            logger.error("while connect database : ", ex);
            if (rst != null) {
                try {
                    rst.close();
                } catch (SQLException e) {
                    logger.error(e);
                } finally {
                    rst = null;
                }
            }
            throw new CollectorException(ex);
        }

        return propValArr;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "ServerName", "DBName" };
    }

    @Override
    public String[] getPropMeta() {
        return new String[] { "DataSpaceSize", "FreeDataSpaceSize", "LogSpaceSize", "FreeLogSpaceSize", "DataSpaceUsage", "LogSpaceUsage" };
    }

    private float formatDecimal(float num) {
        DecimalFormat fmt = new DecimalFormat("#.00");
        try {
            num = Float.parseFloat(fmt.format(num));
        } catch (NumberFormatException e) {
            logger.error("failed to format decimal: ", e);

            return 0.0F;
        }
        return num;
    }
}
